#include "master.h"
#include <shlwapi.h>
#include <commctrl.h>
#include <dshow.h>
#include <stdlib.h>
#include <stdio.h>
#include "gui.h"
#include "comfunct/comfunct.h"

void ControlCreate(HWND hwnd)
{
     HWND hVolumeSlider = NULL, hVolumeText = NULL, hFileName = NULL, hSlider = NULL, hAudioText = NULL,
		  hPlay = NULL, hPause = NULL, hStop = NULL, hOpenFile = NULL, hStatus = NULL, hElapsedTime = NULL,
		  hTotalTime = NULL, hDivide = NULL, hLyricsBox = NULL, hLyricsTitle = NULL, hPlaylistTitle = NULL,
		  hPlaylistItems = NULL;
     const int iStatwidths[] = {70, 280, -1};
     int iTrackbarWidth = 0;
     extern LPTSTR szVolume;
     extern signed long PlayVolume;
	 LVCOLUMN lvc = {0};
	 HGDIOBJ hfDefault = NULL;
	 HMODULE hThemeDll = LoadLibrary(TEXT("uxtheme.dll")), hAudioPlayer = GetModuleHandle(NULL);
	 
	 if(hThemeDll == NULL)
	 {
          iTrackbarWidth = 17; /* Make the width of the slider tabs smaller on 9x/Me */
     }
     else
     {
          iTrackbarWidth = 21;
          FreeLibrary(hThemeDll);
     }
     
	 WindowCreate(&hAudioText, TEXT("EDIT"), GetLocalText(0), WS_CHILD | WS_DISABLED | ES_MULTILINE | ES_READONLY | SS_CENTER | WS_VISIBLE, 6, 13, 33, 28, hwnd, IDI_AUDIOTEXT, hAudioPlayer);
     WindowCreate(&hFileName, TEXT("EDIT"), TEXT(""), WS_CHILD | ES_AUTOHSCROLL | ES_LEFT | WS_VISIBLE | SS_NOPREFIX, 42, 19, 208, 13, hwnd, IDI_FILENAME, hAudioPlayer);
     WindowCreate(&hOpenFile, TEXT("BUTTON"), TEXT("..."), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_TEXT, 254, 18, 20, 15, hwnd, IDI_FILE_OPEN, hAudioPlayer);
     WindowCreate(&hPlay, TEXT("BUTTON"), GetLocalText(1), WS_CHILD | WS_VISIBLE | WS_DISABLED | BS_PUSHBUTTON | BS_TEXT, 14, 43, 50, 19, hwnd, IDI_CONT_PLAY, hAudioPlayer);
     WindowCreate(&hPause, TEXT("BUTTON"), GetLocalText(2), WS_CHILD | WS_VISIBLE | WS_DISABLED | BS_PUSHBUTTON | BS_TEXT, 110, 43, 56, 19, hwnd, IDI_CONT_PAUSE, hAudioPlayer);
     WindowCreate(&hStop, TEXT("BUTTON"), GetLocalText(3), WS_CHILD | WS_VISIBLE | WS_DISABLED |  BS_PUSHBUTTON | BS_TEXT, 231, 43, 48, 19, hwnd, IDI_CONT_STOP, hAudioPlayer);
     WindowCreate(&hVolumeText, TEXT("EDIT"), GetLocalText(4), WS_CHILD | WS_VISIBLE | WS_DISABLED | SS_CENTER, 280, 2, 35, 17, hwnd, IDI_VOLTEXT, hAudioPlayer);
     WindowCreate(&hSlider, TEXT("msctls_trackbar32"), TEXT(""), WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_GROUP | TBS_HORZ | TBS_NOTICKS, 19, 65, 245, iTrackbarWidth, hwnd, IDI_SLIDER, hAudioPlayer);
     WindowCreate(&hVolumeSlider, TEXT("msctls_trackbar32"), TEXT(""), WS_CHILD | WS_VISIBLE | ES_READONLY | WS_DISABLED | TBS_NOTICKS | TBS_VERT, 290, 13, iTrackbarWidth, 85, hwnd, IDI_VOLUME, hAudioPlayer);
     WindowCreate(&hElapsedTime, TEXT("EDIT"), TEXT(""), WS_CHILD | WS_VISIBLE | WS_DISABLED | ES_READONLY | SS_CENTER, 95, 86, 41, 13, hwnd, IDI_ELAPSED_TIME, hAudioPlayer);
     WindowCreate(&hDivide, TEXT("EDIT"), TEXT("/"), WS_CHILD | WS_DISABLED | SS_LEFT, 137, 86, 5, 13, hwnd, IDI_DIVIDE, hAudioPlayer);
     WindowCreate(&hTotalTime, TEXT("EDIT"), TEXT(""), WS_CHILD | WS_VISIBLE | WS_DISABLED | ES_READONLY | SS_CENTER, 144, 86, 45, 13, hwnd, IDI_TOTAL_TIME, hAudioPlayer);

     WindowCreate(&hLyricsTitle, TEXT("EDIT"), GetLocalText(5), WS_CHILD | WS_VISIBLE | WS_DISABLED | ES_READONLY | SS_CENTER, 0, 130, 290, 15, hwnd, IDI_LYRICS_TITLE, hAudioPlayer);
	 hLyricsBox = CreateWindowEx(WS_EX_WINDOWEDGE, TEXT("EDIT"), TEXT(""), WS_CHILD | WS_VSCROLL | WS_VISIBLE | ES_MULTILINE | ES_LEFT | ES_WANTRETURN | ES_AUTOVSCROLL | ES_READONLY,
                                3, 150, 330, 170, hwnd, (HMENU)IDI_LYRICS, hAudioPlayer, NULL);
	 WindowCreate(&hPlaylistTitle, TEXT("EDIT"), GetLocalText(6), WS_CHILD | WS_VISIBLE | WS_DISABLED | ES_READONLY | SS_CENTER, 325, 0, PLAYLIST_VIEW_WIDTH, 15, hwnd, IDI_PLAYLIST_TITLE, hAudioPlayer);
	 hPlaylistItems = CreateWindow(WC_LISTVIEW, TEXT(""), WS_CHILD | WS_VISIBLE | LVS_SINGLESEL | LVS_REPORT | LVS_NOCOLUMNHEADER, 335, 15, PLAYLIST_VIEW_WIDTH, 125, hwnd,
									(HMENU)IDI_PLAYLIST_VIEW, hAudioPlayer, NULL);
	 ListView_SetExtendedListViewStyleEx(hPlaylistItems, 0, 0x00000020); /* LVS_EX_FULLROWSELECT not in my version of the MinGW headers so I use its numeric value here */
	 lvc.mask = LVCF_FMT | LVCF_WIDTH;
	 lvc.fmt = LVCFMT_LEFT;
	 ListView_InsertColumn(hPlaylistItems, 1, &lvc);
	 lvc.cx = PLAYLIST_VIEW_WIDTH;
	 ListView_InsertColumn(hPlaylistItems, 0, &lvc);

     hStatus = CreateStatusWindow(WS_VISIBLE | WS_CHILD, GetLocalText(7), hwnd, IDI_STATUS);
     SendDlgItemMessage(hwnd, IDI_STATUS, SB_SETPARTS, 3, (LPARAM)iStatwidths);
     
     SendDlgItemMessage(hwnd, IDI_VOLUME, TBM_SETRANGE, true, MAKELONG(0, (VOLUME_MUTE * -1)));
     SendDlgItemMessage(hwnd, IDI_VOLUME, TBM_SETPOS, TRUE, (LONG)0);
     szVolume = VolumeTextFromLong(PlayVolume, szVolume);
     SetStatus(hwnd, IDI_STATUS, 2, szVolume);
     
     hfDefault = GetStockObject(DEFAULT_GUI_FONT);
     ChangeTextFont(hwnd, hfDefault);
     SetFocus(hFileName);
     SHAutoComplete(hFileName, SHACF_AUTOSUGGEST_FORCE_ON | SHACF_URLALL | SHACF_FILESYSTEM | SHACF_USETAB);
     return;
}

void WindowCreate(HWND* name, LPCTSTR szClassname, LPCTSTR szWindowText, DWORD dwStyle, int xpos, int ypos, int width, int height, HWND hwndParent, int ControlID, HINSTANCE hInstance)
{
    *name = CreateWindow(szClassname, szWindowText, dwStyle, xpos, ypos, width, height, hwndParent, (HMENU)ControlID, hInstance, NULL);
    if(*name == NULL)
    {
       ErrorInfo();
       ErrorMessage(GetLocalText(8));
    }
    return;
}

void ToggleButton(HWND hwnd, bool bState, bool bPlayDisable)
{
    if(bPlayDisable == false)
    {
        EnableWindow(GetDlgItem(hwnd, IDI_CONT_PLAY), bState);
    }
    
    EnableWindow(GetDlgItem(hwnd, IDI_CONT_PAUSE), bState);
    EnableWindow(GetDlgItem(hwnd, IDI_CONT_STOP), bState);
    EnableWindow(GetDlgItem(hwnd, IDI_SLIDER), bState);
    EnableWindow(GetDlgItem(hwnd, IDI_VOLUME), bState);
    if(bState == true)
    {
        EnableWindow(GetDlgItem(hwnd, IDI_FILENAME), false);
        EnableWindow(GetDlgItem(hwnd, IDI_FILE_OPEN), false);
    }    
    else 
    {
        EnableWindow(GetDlgItem(hwnd, IDI_FILENAME), true);
        EnableWindow(GetDlgItem(hwnd, IDI_FILE_OPEN), true);
        SendDlgItemMessage(hwnd, IDI_FILENAME, WM_SETTEXT, 0, (LPARAM)TEXT(""));
    }
    return;
}

void ElapsedTimeUpdate(HWND hwnd, REFERENCE_TIME rtTimeNow)
{
     unsigned int nSeconds = 0, nHours = 0, nMins = 0;
     TCHAR szHours[6] = TEXT("");
	 TCHAR szMinSecs[7] = TEXT("");
	 TCHAR ElapsedTimeString[14] = TEXT("");
     
     nSeconds = rtTimeNow / (MILLISECS_DIVIDE*1000);
	 nHours = nSeconds / 60 / 60;
	 nSeconds %= 3600;
	 nMins = nSeconds / 60;
	 nSeconds %= 60;
	 
	 if(nHours != 0)
	 {
          _sntprintf(szHours, 5, TEXT("%u:"), nHours);
          _tcsncat(ElapsedTimeString, szHours, 13);
     }
     _sntprintf(szMinSecs, 6, TEXT("%02u:%02u"), nMins, nSeconds);
     _tcsncat(ElapsedTimeString, szMinSecs, 6);
     SendDlgItemMessage(hwnd, IDI_ELAPSED_TIME, WM_SETTEXT, 0, (WPARAM)ElapsedTimeString);
     return;
}

void TotalTimeUpdate(HWND hwnd)
{
     extern REFERENCE_TIME FileTimeinNanos;
     unsigned int nSeconds = 0, nHours = 0, nMins = 0;
     TCHAR szHours[6] = TEXT("");
     TCHAR szMinSecs[7] = TEXT("");
     TCHAR TotalTimeString[14] = TEXT("");
     
     nSeconds = FileTimeinNanos / (MILLISECS_DIVIDE*1000);
	 nHours = nSeconds / 60 / 60;
	 nSeconds %= 3600;
	 nMins = nSeconds / 60;
	 nSeconds %= 60;
	 	 
	 if(nHours != 0)
	 {
          _sntprintf(szHours, 5, TEXT("%u:"), nHours);
          _tcsncat(TotalTimeString, szHours, 13);
     }
     _sntprintf(szMinSecs, 6, TEXT("%02u:%02u"), nMins, nSeconds);
     _tcsncat(TotalTimeString, szMinSecs, 6);
     SendDlgItemMessage(hwnd, IDI_TOTAL_TIME, WM_SETTEXT, 0, (WPARAM)TotalTimeString);
     return;
}

void ClearTimes(HWND hwnd)
{
     SetDlgItemText(hwnd, IDI_ELAPSED_TIME, TEXT(""));
     SetDlgItemText(hwnd, IDI_TOTAL_TIME, TEXT(""));
     ShowWindow(GetDlgItem(hwnd, IDI_DIVIDE), SW_HIDE);
     return;
}

/*
   Function: VolumeTextFromLong
   Description: Takes the volume passed to it, works out the percentage of the maximum volume,
                and copies it into a 5 character long piece of memory which it then returns.
                Before the program exits, the pointer returned (usually contained in szVolume)
                must be passed to free().
   
   Parameters: signed long - the volume to work out the percentage of, from 0 (100%) to Volume_Mute (-6000) (0%)
               LPTSTR - The previous value returned by the function or NULL on first calling.
                        
   Return value: A pointer to the allocated memory containing the volume percentage string.                 

*/

LPTSTR VolumeTextFromLong(signed long lCurrentVolume, LPTSTR szPreviousAlloc)
{
    TCHAR* szVolumeString = realloc(szPreviousAlloc, 5 * sizeof(TCHAR)); /* If szPreviousAlloc is NULL then realloc behaves just like malloc */
    float flPercentVol = (float)lCurrentVolume / (float)VOLUME_MUTE; /* We can't simply use the result of this calculation multiplied by 100 as passing in Volume_Mute as the first parameter would result is 100% */
	float flActualVolume = 0.0f;
    
    if(flPercentVol < 0.5) /* For example: flPercentvol = 0.3 */
    {
        float fldifference = flPercentVol - 0.5f; /* fldifference = -0.2, flPercentvol still = 0.3 */
        fldifference = fldifference * 2; /* fldifference = -0.4 */
        flPercentVol -=  fldifference; /* Taking away a negative number is the same as adding it's positive counterpart
                                          so here, flPercentvol = 0.7. So an initial flPercentVol of 0.3 results in 70% volume */
    }
    else
    {
        float fldifference = 0.5f - flPercentVol;
        fldifference = fldifference * 2;
        flPercentVol += fldifference;
    }
    flActualVolume = flPercentVol * 100.0f;
    _sntprintf(szVolumeString, 5, TEXT("%3.f%%"), flActualVolume);
    return szVolumeString;
}

TCHAR* GetStatusText(HWND hwnd, int iBarPart)
{
    TCHAR* szStatusText = NULL;
    LRESULT TextInfo = SendDlgItemMessage(hwnd, IDI_STATUS, SB_GETTEXTLENGTH, iBarPart, 0);
    WORD TextLength = LOWORD(TextInfo);
    szStatusText = malloc((TextLength * sizeof(TCHAR)) + sizeof(TCHAR));
    SendDlgItemMessage(hwnd, IDI_STATUS, SB_GETTEXT, iBarPart, (LPARAM)szStatusText);
    
    return szStatusText;
}

void ChangeBackgroundColor(HWND hwnd, HBRUSH* hbrBackBrush)
{
	CHOOSECOLOR cc = {0};
	static COLORREF rgbCustomColors[16] = {0};
	COLORREF rgbBackColor = GetSysColor(COLOR_WINDOW); /* Initialise the color to the default background color */
	cc.lStructSize = sizeof(CHOOSECOLOR);
	cc.hwndOwner = hwnd;
	cc.rgbResult = rgbBackColor;
	cc.Flags = CC_ANYCOLOR | CC_RGBINIT;
	cc.lpCustColors = (LPDWORD)rgbCustomColors;

	if(ChooseColor(&cc))
	{
		DeleteObject(*hbrBackBrush);
		*hbrBackBrush = CreateSolidBrush(cc.rgbResult);
	}
	return;
}

BOOL CALLBACK SetChildWindowsTransparency(HWND hwnd, LPARAM lParam)
{
	LPCTSTR szClassName[] = {TEXT("EDIT"), TEXT("BUTTON"), TEXT("msctls_trackbar32")};
	TCHAR szWindowClassName[20] = {0};

	GetClassName(hwnd, szWindowClassName, 20);
	if(_tcsicmp(szWindowClassName, szClassName[0]) == 0) /* Edit window */
	{
		SendMessage(hwnd, WM_CTLCOLOREDIT, (WPARAM)GetWindowDC(hwnd), (LPARAM)hwnd);
	}
	else if(_tcsicmp(szWindowClassName, szClassName[1]) == 0) /* Button window */
	{
		SendMessage(hwnd, WM_CTLCOLORBTN, (WPARAM)GetWindowDC(hwnd), (LPARAM)hwnd);
	}
	else if(_tcsicmp(szWindowClassName, szClassName[2]) == 0) /* Trackbar window */
	{
		SendMessage(hwnd, WM_KILLFOCUS, (WPARAM)NULL, 0); /* Repaints the trackbar's background */
	}
	return true;
}

void AdjustWindowHeight(HWND hwnd, int iHeightAddition)
{
	WINDOWPLACEMENT wp = {sizeof(WINDOWPLACEMENT), 0}, wpPlaylistItems = {sizeof(WINDOWPLACEMENT), 0};
	HWND hPlaylistItems = GetDlgItem(hwnd, IDI_PLAYLIST_VIEW);
	GetWindowPlacement(hwnd, &wp);
	GetWindowPlacement(hPlaylistItems, &wpPlaylistItems);
    wp.rcNormalPosition.bottom += iHeightAddition;
	wpPlaylistItems.rcNormalPosition.bottom += iHeightAddition;
	SetWindowPlacement(hPlaylistItems, &wpPlaylistItems);
	SetWindowPlacement(hwnd, &wp);    
    return;
}

void AdjustWindowWidth(HWND hwnd, int iWidthAddition)
{
     WINDOWPLACEMENT wp = {sizeof(WINDOWPLACEMENT), 0};
     GetWindowPlacement(hwnd, &wp);
     wp.rcNormalPosition.right += iWidthAddition;
     SetWindowPlacement(hwnd, &wp);
     return;
}

HWND GetAPWindow(void)
{
	return FindWindow(TEXT("AudioPlayer"), TEXT("AudioPlayer"));
}
